﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.Wpf;

namespace wpf_sample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        Microsoft.Web.WebView2.Wpf.WebView2 wpf_wv;
        Microsoft.Web.WebView2.Core.CoreWebView2 core_wv;
        public MainWindow()
        {
            InitializeComponent();
        }

        private static class NativeMethods
        {
            [Flags]
            public enum WS : uint
            {
                None = 0,
                CLIPCHILDREN = 0x02000000,
                VISIBLE = 0x10000000,
                CHILD = 0x40000000,
            }

            [Flags]
            public enum WS_EX : uint
            {
                None = 0,
                TRANSPARENT = 0x00000020,
            }

            public enum WM : uint
            {
                SETFOCUS = 0x0007,
                PAINT = 0x000F,
            }

            [StructLayout(LayoutKind.Sequential)]
            public struct Rect
            {
                public int left;
                public int top;
                public int right;
                public int bottom;
            }

            [StructLayout(LayoutKind.Sequential)]
            public struct PaintStruct
            {
                public IntPtr hdc;
                public bool fErase;
                public Rect rcPaint;
                public bool fRestore;
                public bool fIncUpdate;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public byte[] rgbReserved;
            }

            [DllImport("user32.dll", SetLastError = true)]
            public static extern IntPtr BeginPaint(IntPtr hwnd, out PaintStruct lpPaint);

            [DllImport("user32.dll", SetLastError = true)]
            public static extern bool EndPaint(IntPtr hwnd, ref PaintStruct lpPaint);

            [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern IntPtr CreateWindowExW(
                WS_EX dwExStyle,
                [MarshalAs(UnmanagedType.LPWStr)] string lpClassName,
                [MarshalAs(UnmanagedType.LPWStr)] string lpWindowName,
                WS dwStyle,
                int x,
                int y,
                int nWidth,
                int nHeight,
                IntPtr hWndParent,
                IntPtr hMenu,
                IntPtr hInstance,
                IntPtr lpParam);

            [DllImport("user32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool DestroyWindow(IntPtr hwnd);
        }

        public class HwndForWV2 : HwndHost
        {
            protected override HandleRef BuildWindowCore(HandleRef hwndParent)
            {
                IntPtr hwnd = NativeMethods.CreateWindowExW(
                    NativeMethods.WS_EX.TRANSPARENT,
                    "static",
                    string.Empty,
                    NativeMethods.WS.CHILD | NativeMethods.WS.VISIBLE | NativeMethods.WS.CLIPCHILDREN,
                    0,
                    0,
                    0,
                    0,
                    hwndParent.Handle,
                    IntPtr.Zero,
                    Marshal.GetHINSTANCE(typeof(NativeMethods).Module),
                    IntPtr.Zero
                );
                return new HandleRef(null, hwnd);
            }

            protected override void DestroyWindowCore(HandleRef hwnd)
            {
                NativeMethods.DestroyWindow(hwnd.Handle);
            }

            protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
            {
                return base.WndProc(hwnd, msg, wParam, lParam, ref handled);
            }
        }

        void WpfWebView_NavigationStarting(object sender, CoreWebView2NavigationStartingEventArgs e)
        {
            string profileName = wpf_wv.CoreWebView2.Profile.ProfileName;
            bool isInPrivateModeEnabled = wpf_wv.CoreWebView2.Profile.IsInPrivateModeEnabled;
            MessageBox.Show($"wpf wv profile name = {profileName}, private mode = {isInPrivateModeEnabled}");
        }

        void CoreWebView_NavigationStarting(object sender, CoreWebView2NavigationStartingEventArgs e)
        {
            string profileName = core_wv.Profile.ProfileName;
            bool isInPrivateModeEnabled = core_wv.Profile.IsInPrivateModeEnabled;
            MessageBox.Show($"core wv profile name = {profileName}, private mode = {isInPrivateModeEnabled}");
        }

        private async void CreateWpfWV2(object sender, RoutedEventArgs e)
        {
            CoreWebView2CreationProperties properties = new CoreWebView2CreationProperties();
            properties.ProfileName = "profile_wpf";
            properties.IsInPrivateModeEnabled = false;
            wpf_wv = new WebView2();
            wpf_wv.CreationProperties = properties;

            Window window = new Window();
            window.Content = wpf_wv;
            window.Show();
            await wpf_wv.EnsureCoreWebView2Async();

            wpf_wv.Source = new Uri("https://www.bing.com");
            wpf_wv.NavigationStarting += WpfWebView_NavigationStarting;
        }

        private async void CreateCoreWV2(object sender, RoutedEventArgs e)
        {
            var hwnd = new HwndForWV2();
            Window window = new Window();
            window.Content = hwnd;
            window.Show();

            var env = await CoreWebView2Environment.CreateAsync();
            var options = env.CreateCoreWebView2ControllerOptions();
            options.ProfileName = "profile_core";
            options.IsInPrivateModeEnabled = true;
            var controller = await env.CreateCoreWebView2ControllerAsync(hwnd.Handle, options);
            core_wv = controller.CoreWebView2;

            controller.Bounds = new System.Drawing.Rectangle(0, 0, 800, 600);
            core_wv.Navigate("https://www.bing.com/");
            core_wv.NavigationStarting += CoreWebView_NavigationStarting;
        }
    }
}
